package org.future.dev.xml;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/**
 * 读写 xml 文件
 * 
 * @date 2009-12-8 下午07:22:07
 */
public class XmlUtils {
    /**
     * 创建一个 xml 文件
     * 
     * @param file_path
     */
    public void write(String file_path) {
        // 文件输出流
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(file_path);
            // 新建 format 用来格式化 xml 文件
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("utf-8");                         // 编码格式
            format.setIndentSize(4);                             // Tab 缩进
            XMLWriter writer = new XMLWriter(out, format);
            Document document = DocumentHelper.createDocument(); // 创建文档
            Element root = document.addElement("beans");         // 创建根节点
            // //////////////// one /////////////////////
            Element node = root.addElement("student");
            Element id = node.addElement("id");
            Element name = node.addElement("name");
            Element age = node.addElement("age");
            id.addText("001");
            name.addText("孙悟空");
            age.addText("500");
            // //////////////// two /////////////////////
            node = root.addElement("student");
            id = node.addElement("id");
            name = node.addElement("name");
            age = node.addElement("age");
            id.addText("002");
            name.addText("猪八戒");
            age.addText("300");
            // //////////////// three /////////////////////
            node = root.addElement("student");
            id = node.addElement("id");
            name = node.addElement("name");
            age = node.addElement("age");
            id.addText("003");
            name.addText("沙和尚");
            age.addText("200");
            // 写到文件中
            writer.write(document);
            writer.flush();
            writer.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException ioe) {
        }
    }

    /**
     * 读取一个 xml 文件
     * 
     * @param file_path
     */
    public void read(String file_path) {
        FileInputStream in = null;
        SAXReader reader = null;
        try {
            in = new FileInputStream(file_path);
            reader = new SAXReader();
            Document document = reader.read(in);                // 获得文档
            Element root = document.getRootElement();           // 获得根节点
            List<Element> list = root.selectNodes("student");   // 获得所有 student 子节点
            // 输出头信息
            Object[] header = { "id", "name", "age" };
            System.out.println("+---------+----------+---------+");
            System.out.format("|%8s | %8s |%8s |\n", header);
            System.out.println("+---------+----------+---------+");
            for (int i = 0; i < list.size(); i++) {
                Element el = list.get(i);
                Iterator<Element> fields = el.elementIterator();
                Object[] args = new Object[4];
                int index = 0;
                while (fields.hasNext()) {
                    Element field = fields.next();
                    args[index++] = field.getText();
                }
                System.out.format("|%8s | %7s |%8s |\n", args);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (org.dom4j.DocumentException docE) {

        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 从 xml 文件中读取一个 List
     * 
     * @param file_path
     * @param cls
     * @return
     */
    public static List getList(String file_path, Class cls, String xpath) {
        FileInputStream in = null;
        SAXReader reader = null;
        Object obj = null;
        List beanList = new ArrayList();
        try {
            in = new FileInputStream(file_path);
            reader = new SAXReader();
            Document document = reader.read(in);            // 获得文档
            Element root = document.getRootElement();       // 获得根节点
            List<Element> list = root.selectNodes(xpath);   // 根据 xpath 获取子节点
            // 实例化一个构造器
            Constructor cons = cls.getDeclaredConstructor(); // 默认构造函数
            // 遍历子节点
            for (int i = 0; i < list.size(); i++) {
                Element el = list.get(i);
                // 新建一个对象
                obj = cons.newInstance();
                // 返回所有声明的域 ,包括 private 的域
                Field[] fds = cls.getDeclaredFields();
                // 构造 set 方法
                String fname = "";                          // 域名称
                String setMethod = "";                      // set 方法名称
                for (int j = 0; j < fds.length; j++) {
                    fname = fds[j].getName();               // 取出字段名称
                    setMethod = "set"                       // 构造 set 方法
                            + Character.toUpperCase(fname.charAt(0))
                            + fname.substring(1);
                    // 创建 Method
                    Method m = cls.getMethod(setMethod, String.class);
                    // 取出注解
                    XmlField f = fds[j].getAnnotation(XmlField.class);
                    if (f == null) {                        // 当前属性没有使用该注解
                        continue;
                    }
                    String label = f.label();
                    if (label.equals("")) {                 // 注解值为空
                        continue;
                    }
                    String val = el.elementText(label);     // 根据注解取出 xml 中对应的 text
                    // 调用 setMethod 方法
                    m.invoke(obj, val);                     // 将对象加入到 List 中
                }
                beanList.add(obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return beanList;
    }

    /**
     * 将 List 保存到 xml 中
     * 
     * @param file_path
     * @param list
     */
    public static void saveList(String file_path, List list, String elementName) {
        if (list == null || list.size() < 1) {              // 没有数据需要保存
            return;
        }
        // 文件输出流
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(file_path);
            // 新建 format 用来格式化 xml 文件
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("utf-8");                         // 编码格式
            format.setIndentSize(4);                             // Tab 缩进
            XMLWriter writer = new XMLWriter(out, format);
            Document document = DocumentHelper.createDocument(); // 创建文档
            Element root = document.addElement("beans");         // 创建根节点
            for (int i = 0; i < list.size(); i++) {
                Element node = root.addElement(elementName);
                Object obj = list.get(i);
                Class cls = obj.getClass();
                // 返回所有声明的域,包括 private 的域
                Field[] fds = cls.getDeclaredFields();
                String fname = "";                               // 域名称
                String getMethod = "";                           // get 方法名称
                for (int j = 0; j < fds.length; j++) {
                    fname = fds[j].getName();
                    getMethod = "get" 
                            + Character.toUpperCase(fname.charAt(0))
                            + fname.substring(1);
                    // 创建Method
                    Method m = cls.getMethod(getMethod);
                    // 调用 getMethod 方法
                    String val = (String) m.invoke(obj);
                    // 取出注解
                    XmlField f = fds[j].getAnnotation(XmlField.class);
                    if (f == null) {                             // 当前属性没有使用该注解
                        continue;
                    }
                    String label = f.label();
                    if (label.equals("")) {                      // 注解值为空
                        continue;
                    }
                    Element el = node.addElement(label);
                    el.addText(val);
                }
            }
            // 写到文件中
            writer.write(document);
            writer.flush();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
}
